package unit;

import java.util.Arrays;

import junit.framework.TestCase;

import com.google.code.netcheckin.io.Ascii;
import com.google.code.netcheckin.util.ByteUtils;

public class UByteUtils extends TestCase {


	private static final byte[] DATA = new byte[] {
		Ascii.V_A,
		Ascii.V_x,
		Ascii.V_e,
		Ascii.V_l,
	};

	private static final byte[] AX = new byte[] {
		Ascii.V_A,
		Ascii.V_x,
	};

	private static final byte[] EL = new byte[] {
		Ascii.V_e,
		Ascii.V_l,
	};

	private static final byte[] TOO_BIG = new byte[] {
		Ascii.V_A,
		Ascii.V_x,
		Ascii.V_e,
		Ascii.V_l,
		Ascii.V_Z,
	};

	private static final byte[] XXX = new byte[] {
		Ascii.V_X,
		Ascii.V_X,
		Ascii.V_X,
	};

	private static final byte[] EMPTY = new byte[0];

	public UByteUtils(String name) {
		super(name);
	}


	public final void testACAreValuesAt() {
		assertTrue("test 1", ByteUtils.areValuesAt(AX, DATA, 0));
		assertFalse("test 2", ByteUtils.areValuesAt(EL, DATA, 0));
		assertFalse("test 3", ByteUtils.areValuesAt(TOO_BIG, DATA, 0));
		assertTrue("test 4", ByteUtils.areValuesAt(EL, DATA, 2));
		assertFalse("test 5", ByteUtils.areValuesAt(EL, DATA, 3));
		assertFalse("test 6", ByteUtils.areValuesAt(EMPTY, DATA, 1));
		assertFalse("test 7", ByteUtils.areValuesAt(AX, EMPTY, 1));
	}

	public final void testADBeginsWith() {
		assertTrue("test 1", ByteUtils.beginsWith(AX, DATA));
		assertFalse("test 2", ByteUtils.beginsWith(EL, DATA));
	}

	public final void testAEEndsWith() {
		assertFalse("test 1", ByteUtils.endsWith(AX, DATA));
		assertTrue("test 2", ByteUtils.endsWith(EL, DATA));
	}

	public final void testAFIndexOfInByte() {
		assertEquals("test 1", 0, ByteUtils.indexOfIn(Ascii.V_A, DATA));
		assertEquals("test 2", 3, ByteUtils.indexOfIn(Ascii.V_l, DATA));
		assertEquals("test 3", -1, ByteUtils.indexOfIn(Ascii.V_BEL, DATA));
	}

	public final void testAGIndexOfInArray() {
		assertEquals("test 1", 0, ByteUtils.indexOfIn(AX, DATA));
		assertEquals("test 2", 2, ByteUtils.indexOfIn(EL, DATA));
		assertEquals("test 3", -1, ByteUtils.indexOfIn(TOO_BIG, DATA));
		assertEquals("test 4", -1, ByteUtils.indexOfIn(XXX, DATA));
		assertEquals("test 5", -1, ByteUtils.indexOfIn(EMPTY, DATA));
	}

	public final void testAHLastIndexOfInByte() {
		assertEquals("test 1", 0, ByteUtils.lastIndexOfIn(Ascii.V_A, DATA));
		assertEquals("test 2", 3, ByteUtils.lastIndexOfIn(Ascii.V_l, DATA));
		assertEquals("test 3", -1, ByteUtils.lastIndexOfIn(Ascii.V_BEL, DATA));
	}

	public final void testAILastIndexOfInArray() {
		assertEquals("test 1", 0, ByteUtils.lastIndexOfIn(AX, DATA));
		assertEquals("test 2", 2, ByteUtils.lastIndexOfIn(EL, DATA));
		assertEquals("test 3", -1, ByteUtils.lastIndexOfIn(TOO_BIG, DATA));
		assertEquals("test 4", -1, ByteUtils.lastIndexOfIn(XXX, DATA));
		assertEquals("test 5", -1, ByteUtils.lastIndexOfIn(EMPTY, DATA));
	}

	public final void testAJToUnsignedInt() {
		byte x = -127;
		assertEquals("test 1", 129, ByteUtils.toUnsignedInt(x));
		x = -1;
		assertEquals("test 2", 255, ByteUtils.toUnsignedInt(x));
		x = 127;
		assertEquals("test 3", 127, ByteUtils.toUnsignedInt(x));
	}

	public final void testAKCastIntToByte() {
				// Does casting work the way that I think?
				// transfers bits as is.
				// If these tests ever fail, there will
				// be problems.
		int intx = 255;
		byte x = (byte) intx;
		assertEquals("test 4", -1, x);
				// bits to the left of those available in
				// the byte are lost
		intx = 257;	// b 1 0000 0001
		x = (byte)intx;
		assertEquals("test 5", 1, x);
	}

	public final void testALsubArrayCount() {
				// take from front
		byte[] result = ByteUtils.subArray(DATA, 0, 2);
		assertTrue("test 1", Arrays.equals(result, AX));
				// take from end
		result = ByteUtils.subArray(DATA, 2, 2);
		assertTrue("test 2", Arrays.equals(result, EL));
	}


	public final void testAMCopyInto() {
		byte[] result = new byte[64];			// plain copy
		int offset = ByteUtils.copyInto(result, 0, DATA);
		assertEquals("1 wrong result offset", DATA.length, offset);
		assertTrue("1 dest does not begin with src", ByteUtils.beginsWith(DATA, result));

		offset = ByteUtils.copyInto(result, 20, DATA);	// offset in dest
		assertEquals("2 wrong result offset", (20 + DATA.length), offset);
		assertTrue("2 dest does not contain src at offset", ByteUtils.areValuesAt(DATA, result, 20));

		offset = ByteUtils.copyInto(result, 30, DATA, 1, 3);	// offset in src
		assertEquals("3 wrong result offset", 32, offset);
		byte[] realsrc = ByteUtils.subArray(DATA, 1, 2);
		assertTrue("3 dest does not contain src at offset", ByteUtils.areValuesAt(realsrc, result, 30));

	}

	public final void testNCopyIntoFixedPadded() {
		byte[] result = new byte[64];			
		Arrays.fill(result, Ascii.V_X);
		// copy 4 bytes (DATA) into 5 byte field
		int offset = ByteUtils.copyIntoFixedPadded(result, 40, 5, DATA);
		assertEquals("1 wrong offset", (40 + DATA.length + 1), offset);
		assertTrue("1 dest does not contain src at offset", 
		  ByteUtils.areValuesAt(DATA, result, 40));
		assertTrue("1 bad padding", 
		  ByteUtils.areValuesAt(new byte[] { Ascii.V_SPACE, Ascii.V_X },
		  result, (offset - 1)));
		// copy 5 bytes into 4-byte field
		Arrays.fill(result, Ascii.V_X);
		offset = ByteUtils.copyIntoFixedPadded(result, 0, 4, TOO_BIG);
		assertEquals("2 wrong offset", (TOO_BIG.length - 1), offset);
		assertFalse("2 everything copied", ByteUtils.areValuesAt(TOO_BIG, result, 0));
		assertTrue("2 wrong result", 
		ByteUtils.areValuesAt(
		ByteUtils.subArray(TOO_BIG, 0, (TOO_BIG.length - 1)), result, 0));
	}

}
